#include "LogicSystem.h"
#include "HttpConnection.h"
#include "const.h"
#include <iostream>
#include "VerifyGrpcClient.h"
#include "RedisMgr.h"
#include "MysqlMgr.h"
#include "data.h"
#include "StatusGrpcClient.h"

bool LogicSystem::HandleGet(std::string path,std::shared_ptr<HttpConnection> conn)
{
    auto it = get_handlers_.find(path);
    if(it!=get_handlers_.end()){
        it->second(conn);
        return true;
    }
    return false;
}

//注册GET请求处理函数
void LogicSystem::RegGet(std::string url,HttpHandler handler)
{
    get_handlers_[url]=handler;
}

LogicSystem::LogicSystem()
{
    RegGet("/get_test",[](std::shared_ptr<HttpConnection> conn){
        beast::ostream(conn->response_.body()) << "receive get_test\n";
        for(auto &elem:conn->get_params_)
        {
            beast::ostream(conn->response_.body()) << elem.first << ":" << elem.second << std::endl;
        }
        conn->response_.result(http::status::ok);
        conn->response_.set(http::field::content_type,"text/plain; charset=utf-8");
    });

    RegPost("/get_verifycode",std::bind(&LogicSystem::GetVerifyCodeHandler,this,std::placeholders::_1));
    RegPost("/user_register",std::bind(&LogicSystem::RegisterUserHandler,this,std::placeholders::_1));
    RegPost("/reset_pwd",std::bind(&LogicSystem::ResetPasswordHandler,this,std::placeholders::_1));
    RegPost("/user_login",std::bind(&LogicSystem::LoginUserHandler,this,std::placeholders::_1));
}




void LogicSystem::RegPost(std::string url,HttpHandler handler)
{
    post_handlers_[url]=handler;
}

bool LogicSystem::HandlePost(std::string url,std::shared_ptr<HttpConnection> conn)
{
    auto it = post_handlers_.find(url);
    if(it!=post_handlers_.end()){
        it->second(conn);
        return true;
    }
    return false;
}


void LogicSystem::GetVerifyCodeHandler(std::shared_ptr<HttpConnection> conn)
{

    conn->response_.result(http::status::ok);
    conn->response_.set(boost::beast::http::field::content_type,"application/json");
    //拿到请求体中的json字符串
    auto body_str = boost::beast::buffers_to_string(conn->request_.body().data());
    std::cout<<"receive body is "<<body_str<<std::endl;
    //解析json字符串
    Json::Reader reader;
    Json::Value value;
    Json::Value root;
    if(!reader.parse(body_str,value))
    {
        std::cout<<"parse json failed"<<std::endl;
        root["error"]=ErrorCodes::Error_Json;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }
    //从json中取email
    auto email = value["email"].asString();
    std::cout<<"email is "<<email<<std::endl;

    //此处调用gRPC服务拿到验证码
    auto response = VerifyGrpcClient::GetInstance()->GetVerifyCode(email);


    root["code"]=response.code();
    root["error"]=response.error();
    root["email"]=email;
    std::string json_str = root.toStyledString();
    boost::beast::ostream(conn->response_.body())<<json_str;
    
    return;
}


void LogicSystem::RegisterUserHandler(std::shared_ptr<HttpConnection> conn)
{
    conn->response_.result(http::status::ok);
    conn->response_.set(boost::beast::http::field::content_type,"application/json");
    //先拿到请求体中的json字符串
    auto body_str = boost::beast::buffers_to_string(conn->request_.body().data());
    std::cout<<"receive body is "<<body_str<<std::endl;
    Json::Reader reader;
    Json::Value root;
    Json::Value src_root;
    bool parse_success = reader.parse(body_str,src_root);
    if(!parse_success)
    {
        std::cerr<<"parse json failed"<<std::endl;
        root["error"]=ErrorCodes::Error_Json;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }
    std::string email = src_root["email"].asString();
    std::string name = src_root["user"].asString();
    std::string pwd = src_root["passwd"].asString();
    std::string confirm = src_root["confirm"].asString();
    

    //判断密码和确认密码是否相同
    if (pwd!=confirm)
    {
        root["error"]=ErrorCodes::PasswdErr;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }




    
    std::string verify_code="";
    //到Redis中查找email对应的验证码是否匹配
    RedisMgr::GetInstance()->Get(CODEPREFIX + email,verify_code);
    if (verify_code=="")
    {
        root["error"]=ErrorCodes::VerifyExpired;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }
    

    if (verify_code!=src_root["verifycode"].asString())
    {
        root["error"]=ErrorCodes::VerifyCodeErr;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }
    //TODO 到数据库中去查找用户是否存在
    
    int uid = MysqlMgr::GetInstance()->RegUser(name,email,pwd);
    if(uid==-1||uid==0)
    {
        std::cout << " user or email exist" << std::endl;
        root["error"] = ErrorCodes::UserExist;
        std::string jsonstr = root.toStyledString();
        beast::ostream(conn->response_.body()) << jsonstr;
        return;
    }

    
    root["error"] = ErrorCodes::Success;
    root["email"] = email;
    root ["user"]= name;
    root["passwd"] = pwd;
    root["confirm"] = confirm;
    root["verifycode"] = src_root["verify_code"].asString();
    std::string json_str = root.toStyledString();
    boost::beast::ostream(conn->response_.body())<<json_str;
    return;
}


void LogicSystem::ResetPasswordHandler(std::shared_ptr<HttpConnection> conn)
{
    conn->response_.result(http::status::ok);
    conn->response_.set(boost::beast::http::field::content_type,"application/json");
    //拿到body中的数据
    std::string body_str= boost::beast::buffers_to_string(conn->request_.body().data());
    std::cout<<"receive body is "<<body_str<<std::endl;

    Json::Reader reader;
    Json::Value root;
    Json::Value src_root;
    bool parse_success = reader.parse(body_str,src_root);
    if(!parse_success)
    {
        std::cerr<<"parse json failed"<<std::endl;
        root["error"]=ErrorCodes::Error_Json;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }

    //从json中取出数据
    std::string name = src_root["user"].asString();
    std::string email = src_root["email"].asString();
    std::string pwd = src_root["passwd"].asString();
    std::string verifycode = src_root["verifycode"].asString();

    //到Redis中查找验证码是否匹配
    std::string verify_code="";
    RedisMgr::GetInstance()->Get(CODEPREFIX + email,verify_code);
    if(verify_code=="")
    {
        std::cout<<"VerifyCode is expired"<<std::endl;
        root["error"]=ErrorCodes::VerifyExpired;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }

    if (verify_code!=verifycode)
    {
        root["error"]=ErrorCodes::VerifyCodeErr;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }

    //在验证码匹配的情况下，到数据库中去查找用户名和邮箱是否匹配
    bool email_exist = MysqlMgr::GetInstance()->CheckEmail(name,email);
    if (!email_exist)
    {
        root["error"]=ErrorCodes::EmailNotMatch;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }
    //结果为true，修改密码，依据用户名来修改密码
    bool passwd_update = MysqlMgr::GetInstance()->UpdatePassword(name,pwd);
    if(!passwd_update)
    {
        root["error"]=ErrorCodes::PasswdUpFailed;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }
    //输出成功修改密码
    std::cout<<"Reset Password Success"<<std::endl;

    root["error"]= ErrorCodes::Success;
    root["email"] = email;
    root["user"] = name;
    std::string jsonstr = root.toStyledString();
    boost::beast::ostream(conn->response_.body())<<jsonstr;
    return;
}


void LogicSystem::LoginUserHandler(std::shared_ptr<HttpConnection> conn)
{
    conn->response_.result(http::status::ok);
    conn->response_.set(boost::beast::http::field::content_type,"application/json");
    //拿到body中的数据
    std::string body_str = boost::beast::buffers_to_string(conn->request_.body().data());
    std::cout<<"receive body is "<<body_str<<std::endl;

    Json::Reader reader;
    Json::Value root;
    Json::Value src_root;
    bool parse_success = reader.parse(body_str,src_root);
    if(!parse_success)
    {
        std::cerr<<"parse json failed\n";
        root["error"] = ErrorCodes::Error_Json;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }
    //从json中取出数据
    std::string name = src_root["user"].asString();
    std::string pwd = src_root["pwd"].asString();
    




    UserInfo userinfo;
    //到数据库中查询用户和密码是否匹配
    bool user_exist = MysqlMgr::GetInstance()->CheckPwd(name,pwd,userinfo);
    if(!user_exist)
    {
        std::cout<<"user or passwd not match"<<std::endl;
        root["error"] = ErrorCodes::PasswdInvalid;
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }
    //TODO 通过gRPC到StatusServer中查询可用的ChatServer服务器，返回ip和token给客户端
    //完成用户类的定义，完成json的填写，返回给客户端。
    message::GetChatServerResponse resp = StatusGrpcClient::GetInstance()->GetChatServer(userinfo.uid);
    if (resp.error()!=ErrorCodes::Success)
    {
        root["error"] = resp.error();
        std::string json_str = root.toStyledString();
        boost::beast::ostream(conn->response_.body())<<json_str;
        return;
    }
    

    //将RPC返回的ChatServer信息填写到json中
    root["error"] = ErrorCodes::Success;
    root["host"] = resp.host();
    root["port"]=resp.port();
    root["token"] = resp.token();
    root["user"]=name;
    root["uid"] = userinfo.uid;
    root["email"] = userinfo.email;


    std::string jsonstr = root.toStyledString();
    boost::beast::ostream(conn->response_.body())<<jsonstr;
    return;
}